package main

import (
	"context"
	"errors"
	"fmt"
	xerrors "github.com/pkg/errors"
	"golang.org/x/sync/errgroup"
	"net/http"
	"os"
	"os/signal"
	"syscall"
	"time"
)

func main() {
	eg, ctx := errgroup.WithContext(context.Background())
	mux := http.NewServeMux()
	mux.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) {
		writer.Write([]byte("hello world"))
	}) 
	server := http.Server{
		Handler: mux,
		Addr:    ":8080",
	}

	eg.Go(func() error {
		err :=  server.ListenAndServe()
		return xerrors.Wrap(err, fmt.Sprintf("server shutdowm, reason is %s", err.Error()))
	})
	
	eg.Go(func() error {
		//监控是否已经收到系统退出信号，如果收到，则主动关闭server
		select {
		case <- ctx.Done():
			ctxT, cancel := context.WithTimeout(context.Background(), time.Second * 3)
			defer cancel()
			return server.Shutdown(ctxT)
		}
	})

	eg.Go(func() error {
		//启动一个携程，监控退出信号
		quit := make(chan os.Signal, 0)
		signal.Notify(quit, syscall.SIGTERM, syscall.SIGHUP, syscall.SIGKILL)

		select {
		case <-ctx.Done():
			//判断服务是否已经退出，如果退出，则停止监听
			return ctx.Err()
		case sig := <-quit:
			//收到退出信号，cancel ctx，用于通知http server需要关闭
			err := xerrors.Wrap(errors.New(fmt.Sprintf("%v", sig)), fmt.Sprintf("to be quited, reason is : get an %v signal", sig))
			return err
		}
	})

	eg.Wait()
}
